﻿//-----------------------------------------------------------------------------
//<filedescription file="CustomRebootUtils.cs" company="Microsoft">
//  <copyright>
//     Copyright © Microsoft Corporation.  All rights reserved.
//     ***  DESIGNATED SAMPLE CODE (per the included software license terms) ***
//      THIS CODE SAMPLE IS MADE AVAILABLE TO YOU WITHOUT WARRANTY OF ANY KIND
//      AND CONFERS NO RIGHTS ON YOU WHATSOEVER EXCEPT THE RIGHT TO REVIEW IT
//      SOLELY AS A REFERENCE.  THE ENTIRE RISK OF USE OR RESULTS FROM USE OF
//      THIS CODE SAMPLE REMAINS WITH YOU.
//  </copyright>
//  <purpose>
//     Utility methods related to the Custom Reboot Action
//  </purpose>
//  <notes>
//  </notes>
//</filedescription>
//-----------------------------------------------------------------------------


#region Using directives

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using Microsoft.ConfigurationManagement.AdminConsole;
using Microsoft.ConfigurationManagement.AdminConsole.OsdCommon;
using Microsoft.ConfigurationManagement.AdminConsole.TaskSequenceEditor;
using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.Win32;
#endregion

namespace Microsoft.ConfigurationManagement.IntegrationDevelopmentKit.CustomReboot
{
    /// <summary>
    /// 
    /// </summary>
    [System.ComponentModel.ToolboxItem(false)]
    public class CustomRebootUtils
    {
        #region Properties

        private int stepNumber = 0;

        /// <summary>
        ///     
        /// </summary>
        /// <value>
        ///     <para>
        ///         
        ///     </para>
        /// </value>
        /// <remarks>
        ///     
        /// </remarks>
        public int StepNumber
        {
            get { return stepNumber; }
            set { stepNumber = value; }
        }

        private int rebootStepId = -1;

        /// <summary>
        ///     
        /// </summary>
        /// <value>
        ///     <para>
        ///         
        ///     </para>
        /// </value>
        /// <remarks>
        ///     
        /// </remarks>
        public int RebootStepId
        {
            get { return rebootStepId; }
            set { rebootStepId = value; }
        }

        private int totalSteps;

        /// <summary>
        ///     
        /// </summary>
        /// <value>
        ///     <para>
        ///         
        ///     </para>
        /// </value>
        /// <remarks>
        ///     
        /// </remarks>
        public int TotalSteps
        {
            get { return totalSteps; }
            set { totalSteps = value; }
        }

        private string totalRebootSteps;

        /// <summary>
        ///     
        /// </summary>
        /// <value>
        ///     <para>
        ///         
        ///     </para>
        /// </value>
        /// <remarks>
        ///     
        /// </remarks>
        public string TotalRebootSteps
        {
            get { return totalRebootSteps; }
            set { totalRebootSteps = value; }
        }

        #endregion

        #region Constants

        private const string defaultRootKey = "HKEY_LOCAL_MACHINE\\";
        private const string defaultValueType = "REG_SZ";
        private const string regBinary = "REG_BINARY";
        private const string regDWord = "REG_DWORD";
        private const string regExpandString = "REG_EXPAND_SZ";
        private const string regMultiString = "REG_MULTI_SZ";
        private const string regNone = "REG_NONE";
        private const string regQword = "REG_QWORD";
        private const string regString = "REG_SZ";


        // Logical Operator
        private const string ifStatementAndOperator = "and";
        private const string ifStatementOrOperator = "or";
        private const string ifStatementNotOperator = "not";

        // Condition Operator
        private const string operatorExists = "exists";
        private const string operatorNotExists = "notExists";
        private const string operatorEquals = "equals";
        private const string operatorNotEquals = "notEquals";
        private const string operatorGreaterThan = "greater";
        private const string operatorGreaterEqual = "greaterEqual";
        private const string operatorLessThan = "less";
        private const string operatorLessEqual = "lessEqual";

        //======[ begin modification ]=======================
        // modified 9/4/08 by rhearn
        // - Added these constants to avoid using repetitive strings values in methods
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_X86_BOOT_IMAGE_ID = "XXX00000";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_REBOOT_PACKAGE_ID = "XXX00001";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_OEM_TOOLKIT_PACKAGE_ID = "XXX00002";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_OS_INSTALL_PACKAGE_ID = "XXX00003";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_SMSCLIENT_PACKAGE_ID = "XXX00004";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_UNATTEND_PACKAGE_ID = "XXX00005";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_OS_IMAGE_PACKAGE_ID = "XXX00006";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_SYSPREP_PACKAGE_ID = "XXX00007";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_DATA_IMAGE_PACKAGE_ID = "XXX00008";
        /// <summary>
        /// 
        /// </summary>
        public const string DUMMY_DRIVER_PACKAGE_ID = "XXX00009";
        //======[ end modification ]=======================

        #endregion

        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="currentTaskSequenceXml"></param>
        /// <param name="templateXml"></param>
        /// <returns></returns>
        public static XmlDocument MergeTaskSequencesForCustomReboot(XmlDocument currentTaskSequenceXml,  XmlDocument templateXml)
        {
            //task sequence content template:
            //  Task Sequence Package settings (Boot image, category, name, etc.) <<< Retained from existing task sequence
            //  Restart in WinPE     <<< Move from existing task sequence to here
            //  Set Step Variable
            //  [Group] Configure Hardware
            //      [Group] Step 1
            //          Diskpart Clean
            //           [1..n OEM Actions]
            //          Custom Reboot
            //      [Group] Step 2
            //          Format and Partition Disk
            //          Custom Reboot
            //      [Group] Step 3
            //          Format and Partition Disk   << moved from existing task sequence to here
            //             (no reboot)
            //  [Group] Deploy Operating System
            //      
            //      >>>  EXISTING TASK SEQUENCE STEPS / GROUPS MOVED HERE <<<
            //
            //      Set step variable

            if (currentTaskSequenceXml == null)
            {
                throw new ArgumentNullException("currentTaskSequenceXml");
            }

            if (templateXml == null)
            {
                throw new ArgumentNullException("templateXml");
            }

            try
            {
                // get the 'sequence' node for use when we need to add using a node instead of a nodelist
                XmlNode currentSequence = IntegrationKitUtilities.GetXmlNode(currentTaskSequenceXml, "//sequence");
                if (currentSequence == null) 
                {
                    MessageBox.Show("Error getting the 'sequence' node from the current task sequence XML");
                    //MessageBox.Show("currentTaskSequenceXml:\n" + currentTaskSequenceXml.OuterXml);
                    return null;
                }

                // find the "SMS_TaskSequence_RebootAction" step from the current sequence (if it exists - usually the first step)
                // and delete it (since we already have a reboot action at the top)
                XmlNode currentRebootAction = IntegrationKitUtilities.GetXmlNode(currentSequence, ".//step[@name='" + Properties.Resources.Text_RestartInWinPeName + "']");
                if (currentRebootAction != null)
                {
                    if (currentRebootAction.ParentNode != null)
                    {
                        XmlNode rebootParent = currentRebootAction.ParentNode;
                        rebootParent.RemoveChild(currentRebootAction);
                    }
                }
                bool currentStepsExist = true;

                // get the list of all steps and groups in the current task sequence
                XmlNodeList currentSteps = IntegrationKitUtilities.GetXmlNodeList(currentTaskSequenceXml, "//sequence/step | //sequence/group");
                if (currentSteps == null)
                {
                    // If currentSteps is null, that means we're starting from a blank task sequence.
                    // In that case, just transplant the template and don't try to move any current steps.
                    //MessageBox.Show("DEBUG: No current steps found in the current task sequence XML"); 
                    currentStepsExist = false;
                }

                // get the list of all top level steps and groups in the template task sequence
                XmlNodeList templateSteps = IntegrationKitUtilities.GetXmlNodeList(templateXml, "//sequence/step | //sequence/group");
                if (templateSteps == null)
                {
                    // if there are no steps in the template, this is an error
                    MessageBox.Show("Error: No steps found in the task sequence template XML");
                    return null;
                }

                //set the target node for moving existing steps
                XmlNode deployOsNode = null;

                // Import the template steps into the current steps XML (so we can use them for replacement)
                // Since the ImportNode method doesn't accept a nodelist, loop through the list and import the individual nodes
                XmlNode newStep = null;
                foreach (XmlNode templateStep in templateSteps)
                {
                    newStep = currentTaskSequenceXml.ImportNode(templateStep, true);
                    if (newStep == null)
                    {
                        return null;
                    }
                    string groupName = IntegrationKitUtilities.GetXmlAttribute(newStep, "name");
                    if ((string.IsNullOrEmpty(groupName) == false) && 
                        (string.Compare(groupName, Properties.Resources.Text_DeployOperatingSystemGroup, StringComparison.CurrentCultureIgnoreCase) == 0))
                    {
                        deployOsNode = newStep;
                    }
                    // move the newly imported step to the end of the list
                    currentSequence.AppendChild(newStep);
                }

                if (currentStepsExist == true)
                {
                    if (deployOsNode == null)
                    {
                        //MessageBox.Show("DEBUG: Deploy OS node was null");
                        return null;
                    }

                    // now move each of the current steps into the 'Deploy Operating System' node, just above the CustomReboot action
                    foreach (XmlNode currentStep in currentSteps)
                    {
                        deployOsNode.InsertBefore(currentStep, deployOsNode.LastChild);
                    }


                    // find any "SMS_TaskSequence_PartitionDiskAction" actions (in the current steps) and move the first one into the step 3 area
                    XmlNode currentFormatAction = IntegrationKitUtilities.GetXmlNode(currentSequence, "//group[@name='" + Properties.Resources.Text_DeployOperatingSystemGroup + "']//step[@type='SMS_TaskSequence_PartitionDiskAction']");
                    if (currentFormatAction != null)
                    {
                        // find the same step in the template and replace it (to retain any partition settings in the current sequence)
                        XmlNode templateFormatAction = IntegrationKitUtilities.GetXmlNode(currentSequence, "//group[@name='Step 3']//step[@type='SMS_TaskSequence_PartitionDiskAction']");
                        if (templateFormatAction != null)
                        {
                            XmlNode step3Group = IntegrationKitUtilities.GetXmlNode(currentSequence, "//group[@name='Step 3']");
                            if (step3Group != null)
                            {
                                step3Group = step3Group.ReplaceChild(currentFormatAction, templateFormatAction);
                            }
                        }
                    }
                }
               

                if (currentTaskSequenceXml != null)
                {
                    return currentTaskSequenceXml;
                }
                //MessageBox.Show("DEBUG: current task sequence XML was null at the end of MergeTaskSequencesForCustomReboot");
                return null;
            }

            catch (Exception e)
            {
                DialogHelper.ShowMessageBox("Exception encountered during MergeTaskSequencesForCustomReboot.\n\n" + e.Message);
                return null;
            }


        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="taskSequence"></param>
        /// <param name="newStepGroup"></param>
        /// <param name="currentStepNumber"></param>
        /// <param name="newStepNumber"></param>
        /// <returns></returns>
        public IResultObject InsertRebootGroupInTaskSequence(IResultObject taskSequence, IResultObject newStepGroup, string currentStepNumber, string newStepNumber)
        {
            if (taskSequence == null)
            {
                throw new ArgumentNullException("taskSequence");
            }
            if (newStepGroup == null)
            {
                throw new ArgumentNullException("newStepGroup");
            }
            if (string.IsNullOrEmpty(currentStepNumber))
            {
                throw new ArgumentNullException("currentStepNumber");
            }
            if (string.IsNullOrEmpty(newStepNumber))
            {
                throw new ArgumentNullException("newStepNumber");
            }

            try
            {
                string existingStepName = Properties.Resources.Text_StepGroupNamePrefix + " " + currentStepNumber;
                string newStepName = Properties.Resources.Text_StepGroupNamePrefix + " " + newStepNumber;

                List<IResultObject> steps = taskSequence.GetArrayItems("Steps"); //array of SMS_TaskSequence_Steps

                for (int i = 0; i < steps.Count; i++)
                {
                    string stepClass = steps[i]["__CLASS"].StringValue;

                    if (string.Compare(stepClass, "SMS_TaskSequence_Group", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        // this is a group

                        // Modify the existing condition settings - increment the variable value
                        // Note: using this method only changes the value if the variable value matches the 
                        //       currentStepNumber value, otherwise it just returns the object unchanged.
                        steps[i] = ChangeGroupVariableConditionValue(steps[i], currentStepNumber, newStepNumber);

                        // Recurse into the group to handle any other groups inside
                        steps[i] = InsertRebootGroupInTaskSequence(steps[i], newStepGroup, currentStepNumber, newStepNumber);

                        // check to see if this group is the we're searching for
                        string stepName = steps[i]["Name"].StringValue;
                        if (string.Compare(stepName, existingStepName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // This is the group we're looking for to insert the new group before

                            // Rename the existing group
                            steps[i]["Name"].StringValue = newStepName;

                            // Add the new group & action (and increment i because the new step is inserted here)
                            steps.Insert(i, newStepGroup);
                            i++;
                        }
                    }
                }
                taskSequence.SetArrayItems("Steps", steps);
                return taskSequence;
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to update group in task sequence.\n" + e.Message);
                throw;
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="taskSequenceXml"></param>
        /// <param name="configXml"></param>
        /// <returns></returns>
        public static XmlDocument FixPackageReferencesInTaskSequence(ConnectionManagerBase connection, XmlDocument taskSequenceXml, XmlDocument configXml)
        {
            try
            {
                if (connection == null)
                {
                    throw new ArgumentNullException("connection");
                }

                if (taskSequenceXml == null)
                {
                    throw new ArgumentNullException("taskSequenceXml");
                }

                if (configXml == null)
                {
                    throw new ArgumentNullException("configXml");
                }


                // Since package IDs are embedded in command line strings and other locations, the XML needs to be converted
                // to a string so string replacement can be done

                string taskSequenceString = taskSequenceXml.OuterXml;
                if (string.IsNullOrEmpty(taskSequenceString))
                {
                    return null;
                }
                //MessageBox.Show("DEBUG:\nFixPackageReferencesInTaskSequence(): Task sequence string:\n" + taskSequenceString);
                        

                // Get the list of package IDs from the config XML file
                XmlNodeList packageIds = IntegrationKitUtilities.GetXmlNodeList(configXml, "//CustomRebootOptions/PackageIdReplacement/Package");
                if (packageIds == null)
                {
                    return null;
                }

                // loop through the list of IDs, see if the ID exists in the XML
                foreach (XmlNode replacementPackage in packageIds)
                {
                    
                    string newPackageId = string.Empty;
                    string packageId = IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "ID");
                    string packageName = IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "Title");

                    //MessageBox.Show("DEBUG:\nPackage ID to replace: " + packageId + "\nName : " + packageName);
                

                    IntegrationKitUtilities.PackageType packageType =
                        (IntegrationKitUtilities.PackageType)Enum.Parse(
                        typeof(IntegrationKitUtilities.PackageType),
                        IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "PackageType"));
                    string version = IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "VersionNumber");

                    if (string.IsNullOrEmpty(packageId))
                    {
                        continue;
                        //break;
                    }
                    if (string.IsNullOrEmpty(packageName))
                    {
                        continue;
                        //break;
                    }
                    if (packageType < 0)
                    {
                        continue;
                        //break;
                    }


                    if (taskSequenceString.Contains(packageId))
                    {
                        //MessageBox.Show("DEBUG:\nPackage ID exists in the task sequence XML. Replacing...");
                
                        // found the package ID in the task sequence XML
                        // Look up the package by name in ConfigMgr. If no version specified, finds any version
                        IResultObject packages = IntegrationKitUtilities.GetPackageByName((ManagementProvider.WqlQueryEngine.WqlConnectionManager)connection, packageName, packageType, version);
                        if (packages == null)
                        {
                            // no packages found...
                            //MessageBox.Show("DEBUG:\nPackage info not found in SCCM. Can't replace");
                            continue;
                            //break;
                        }
                        if (IntegrationKitUtilities.GetNumberOfChildObjects(packages) > 1)
                        {
                            // skipping because result was more than one item. Can't choose for the user here.
                            //MessageBox.Show("DEBUG:\nMultiple packages found in SCCM. Can't replace.");
                            continue;
                            //break;
                        }
                        if (IntegrationKitUtilities.GetNumberOfChildObjects(packages) == 1)
                        {
                            foreach (IResultObject package in packages)
                            {
                                newPackageId = IntegrationKitUtilities.GetROStringProperty(package, "PackageID");
                                taskSequenceString = taskSequenceString.Replace(packageId, newPackageId);
                                //MessageBox.Show("DEBUG:\nPackage '" + packageId + "' replaced with '" + newPackageId + "'");
                                continue;
                                //break;
                            }
                        }
                    }
                }

                if (string.IsNullOrEmpty(taskSequenceString) == false)
                {
                    taskSequenceXml.RemoveAll();
                    taskSequenceXml.LoadXml(taskSequenceString);
                    //MessageBox.Show("DEBUG:\nRe-loaded task sequence into the XML object");
                                
                }

                return taskSequenceXml;

            }
            catch (Exception e)
            {
                MessageBox.Show("Exception occurred in FixPackageReferencesInTaskSequence():\n" + e.InnerException);
                return null;
            }


        }
        
        /// <summary>
        ///     
        /// </summary>
        /// <param name="connection" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="configXml" type="System.Xml.XmlDocument">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="packageID" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <returns>
        ///     A string value...
        /// </returns>
        public static string GetPackageIdFromReplacementString(ConnectionManagerBase connection, XmlDocument configXml, string packageID)
        {
            XmlNode replacementPackage = IntegrationKitUtilities.GetXmlNode(configXml, "//CustomRebootOptions/PackageIdReplacement/Package[@ID='" + packageID + "']");
            if (replacementPackage != null)
            {
                string packageName = IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "Title");
                IntegrationKitUtilities.PackageType packageType = IntegrationKitUtilities.PackageType.SWDPackage;
                try
                {
                    packageType = (IntegrationKitUtilities.PackageType)Enum.Parse(
                        typeof(IntegrationKitUtilities.PackageType),
                        IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "PackageType"));
                }
                catch(ArgumentException)
                {
                    return null;
                }
                string version = IntegrationKitUtilities.GetXmlAttribute(replacementPackage, "VersionNumber");

                if (string.IsNullOrEmpty(packageName) == false) 
                {
                    // found the package ID in the task sequence XML
                    // Look up the package by name in ConfigMgr. If no version specified, finds any version
                    IResultObject packages = IntegrationKitUtilities.GetPackageByName((ManagementProvider.WqlQueryEngine.WqlConnectionManager)connection, packageName, packageType, version);
                    if ((packages != null) && (IntegrationKitUtilities.GetNumberOfChildObjects(packages) == 1))
                    {
                        foreach (IResultObject package in packages)
                        {
                            string foundPackageId = IntegrationKitUtilities.GetROStringProperty(package, "PackageID");
                            return foundPackageId;
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="group"></param>
        /// <param name="currentValue"></param>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public IResultObject ChangeGroupVariableConditionValue(IResultObject group, string currentValue, string newValue)
        {
            if (group == null)
            {
                throw new ArgumentNullException("group");
            }

            try
            {
                if (group["Condition"].ObjectValue != null)
                {
                    IResultObject condition = group.GetSingleItem("Condition");
                    List<IResultObject> operands = condition.GetArrayItems("Operands");
                    for(int i = 0; i < operands.Count; i++)
                    {
                        if (operands[i].ContainsObjectClass("SMS_TaskSequence_VariableConditionExpression") == false)
                        {
                            continue;
                        }
                        if (string.Compare(
                            operands[i]["Variable"].StringValue,
                            Properties.Resources.RebootStepVariable,
                            StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            continue;
                        }
                        if (string.Compare(
                            operands[i]["Value"].StringValue,
                            currentValue,
                            StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            operands[i]["Value"].StringValue = newValue;
                            condition.SetArrayItems("Operands", operands);
                            group.SetSingleItem("Condition", condition);
                            break;
                        }
                    }
                }
                return group;
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed To enumerate task sequence items: " + e.Message);
                throw;
            }
        }

        /// <summary>
        ///     
        /// </summary>
        /// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="ro" type="Microsoft.ConfigurationManagement.ManagementProvider.IResultObject">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="variableName" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="variableValue" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="conditionOperator" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <returns>
        ///     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        /// </returns>
        public IResultObject AddVariableCondition(ConnectionManagerBase conn, IResultObject ro, string variableName, string variableValue, string conditionOperator)
        {
            if (ro != null)
            {
                if ((variableName != null) && (variableValue != null) && (conditionOperator != null))
                {
                    IResultObject condition = null;
                    if (ro["Condition"].ObjectValue == null)
                    {
                        condition = conn.CreateEmbeddedObjectInstance("SMS_TaskSequence_Condition");
                    }
                    else
                    {
                        condition = ro.GetSingleItem("Condition");
                    }

                    IResultObject variable = conn.CreateEmbeddedObjectInstance("SMS_TaskSequence_VariableConditionExpression");

                    variable["Variable"].StringValue = variableName;
                    variable["Value"].StringValue = variableValue;
                    variable["Operator"].StringValue = conditionOperator;

                    List<IResultObject> operands = condition.GetArrayItems("Operands");
                    operands.Add(variable);
                    condition.SetArrayItems("Operands", operands);
                    ro.SetSingleItem("Condition", condition);
                    return ro;
                }
                else
                {
                    DialogHelper.ShowMessageBox("Error! Condition information passed in to AddVariableCondition was null!");
                    return null;
                }
            }
            else
            {
                DialogHelper.ShowMessageBox("Error! Object passed in to AddVariableCondition was null!");
                return null;
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="wmiClassName"></param>
        /// <param name="packageId"></param>
        /// <returns></returns>
        public IResultObject CreateRebootAction(ConnectionManagerBase conn, string wmiClassName, string packageId)
        {
            if (conn == null)
            {
                throw new ArgumentNullException("conn");
            }
            if (string.IsNullOrEmpty(wmiClassName))
            {
                throw new ArgumentNullException("wmiClassName");
            }
            if (string.IsNullOrEmpty(packageId))
            {
                throw new ArgumentNullException("packageId");
            }

            try
            {
                IResultObject newAction = conn.CreateEmbeddedObjectInstance(wmiClassName);
                if ((newAction == null) ||
                    (string.Compare(newAction.ObjectClass, wmiClassName, StringComparison.OrdinalIgnoreCase) != 0))
                {
                    DialogHelper.ShowMessageBox("Failed to create Reboot action in Task Sequence\n");
                    return null;
                }
                //newAction["CommandLine"].StringValue = @"smsswd.exe /run:" + packageId + " cscript " + Properties.Resources.CustomRebootScriptFilename + " Reboot";
                newAction["PackageID"].StringValue = packageId;
                newAction["Name"].StringValue = Properties.Resources.DefaultDisplay_CustomRebootAction;
                newAction["Description"].StringValue = Properties.Resources.CRA_RebootStepDescription;
                newAction["Enabled"].BooleanValue = true;
                newAction["ContinueOnError"].BooleanValue = false;
                newAction["SupportedEnvironment"].StringValue = "WinPEandFullOS";
                newAction["Timeout"].IntegerValue = 300;

                newAction["AlreadyApplied"].BooleanValue = true;
                newAction["AlreadySetGroups"].BooleanValue = true;
                newAction["ChkMessage"].BooleanValue = false;
                newAction["Message"].StringValue = "";
                newAction["MessageTimeout"].StringValue = "0";
                newAction["StepType"].StringValue = Properties.Resources.CRA_StepTypeReboot;
                newAction["WillReboot"].BooleanValue = true;
                newAction["StepNumber"].IntegerValue = 0;

                newAction["WillRunFromPxe"].BooleanValue = true;
                newAction["UserAccount"].StringValue = "";
                newAction["UserPassword"].StringValue = "";
                
                return newAction;
            }
            catch (Exception e)
            {
                DialogHelper.ShowMessageBox("Failed to create Reboot action in task sequence\n" + e.Message);
                return null;
            }
        }

        //GetTaskStep method removed and placed in the IntegrationKit.OSD code.

        /// <summary>
        ///     
        /// </summary>
        /// <param name="taskSequence" type="Microsoft.ConfigurationManagement.ManagementProvider.IResultObject">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="className" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="username" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <param name="password" type="string">
        ///     <para>
        ///         
        ///     </para>
        /// </param>
        /// <returns>
        ///     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        /// </returns>
        public static IResultObject UpdateUserNameAndPasswordInRebootTask(IResultObject taskSequence, string className, string username, string password)
        {
           
            if (taskSequence == null)
            {
                throw new ArgumentNullException("taskSequence");
            }
            if (string.IsNullOrEmpty(className))
            {
                throw new ArgumentNullException("className");
            }
            if (string.IsNullOrEmpty(username))
            {
                throw new ArgumentNullException("username");
            }
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }

            try
            {
                if (taskSequence.PropertyList.ContainsKey("Steps"))
                {
                    List<IResultObject> steps = taskSequence.GetArrayItems("Steps"); //array of SMS_TaskSequence_Steps

                    for (int i = 0; i < steps.Count; i++)
                    {
                        string stepClass = steps[i]["__CLASS"].StringValue;

                        if (string.Compare(stepClass, "SMS_TaskSequence_Group", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // This is a group. Recurse into the group to handle any other steps inside
                            steps[i] = UpdateUserNameAndPasswordInRebootTask(steps[i], className, username, password);

                        }
                        else if (string.Compare(stepClass, className, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            // this step is the type we're searching for
                            if (steps[i].PropertyList.ContainsKey("UserAccount"))
                            {
                                steps[i]["UserAccount"].StringValue = username;
                            }
                            if (steps[i].PropertyList.ContainsKey("UserPassword"))
                            {
                                steps[i]["UserPassword"].StringValue = password;
                            }
                        }
                    }
                    taskSequence.SetArrayItems("Steps", steps);
                }
                return taskSequence;
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to update step in task sequence.\n" + e.Message);
                throw;
            }
        }



        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A string value...
        ///// </returns>
        //public string EnumerateTaskSequencePackages(ConnectionManagerBase conn)
        //{
        //    IResultObject taskSequencePackages = conn.QueryProcessor.ExecuteQuery("select * from SMS_TaskSequencePackage");
        //    string results = null;
        //    foreach (IResultObject ro in taskSequencePackages)
        //    {
        //        ro.Get();

        //        // Get the lazy properties - Sequence property contains the Task sequence XML.
        //        results = results + "\n" + (ro["Name"].StringValue);
        //        results = results + "\n" + (ro["Sequence"].StringValue);
        //        IntegrationKitUtilities.GetTaskSequenceFromTSPackage(conn, ro);

        //        results = results + "\n";

        //    }
        //    return results;
        //}

        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="taskSequence" type="Microsoft.ConfigurationManagement.ManagementProvider.IResultObject">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="conditionName" type="string">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A bool value...
        ///// </returns>
        //public bool GroupWithConditionExists(IResultObject taskSequence, string conditionName)
        //{
        //    try
        //    {
        //        List<IResultObject> flatStepList = IntegrationKitUtilities.GetFlatTaskSequenceStepList(taskSequence);
        //        IResultObject condition;

        //        IResultObject step = null;
        //        for (int i = 0; i < flatStepList.Count; i++)
        //        {
        //            step = flatStepList[i];
        //            if (string.Compare(step["__CLASS"].StringValue, "SMS_TaskSequence_Group") == 0)
        //            {
        //                if (step["Condition"].ObjectValue != null)
        //                {
        //                    condition = step.GetSingleItem("Condition");
        //                    List<IResultObject> operands = condition.GetArrayItems("Operands");
        //                    foreach (IResultObject operand in operands)
        //                    {
        //                        if (operand.ContainsObjectClass("SMS_TaskSequence_VariableConditionExpression"))
        //                        {
        //                            if (operand["Variable"].StringValue == Properties.Resources.RebootStepVariable)
        //                            {
        //                                return true;
        //                            }
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //        return false;
        //    }
        //    catch (SmsException e)
        //    {
        //        Console.WriteLine("Failed To enumerate task sequence items: " + e.Message);
        //        throw;
        //    }
        //}


        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="taskSequence"></param>
        ///// <param name="currentName"></param>
        ///// <param name="newName"></param>
        ///// <returns></returns>
        //public bool ChangeGroupName(IResultObject taskSequence, string currentName, string newName)
        //{
        //    if (taskSequence == null)
        //    {
        //        throw new ArgumentNullException("taskSequence");
        //    }
        //    if (string.Compare(taskSequence.ObjectClass, "SMS_TaskSequence", StringComparison.OrdinalIgnoreCase) != 0)
        //    {
        //        throw new ArgumentException("Argument not correct object class", "taskSequence");
        //    }

        //    try
        //    {
        //        List<IResultObject> flatStepList = IntegrationKitUtilities.GetFlatTaskSequenceStepList(taskSequence);
        //        IResultObject condition;

        //        IResultObject step = null;
        //        for (int i = 0; i < flatStepList.Count; i++)
        //        {
        //            step = flatStepList[i];
        //            if (string.Compare(step["__CLASS"].StringValue, "SMS_TaskSequence_Group") != 0)
        //            {
        //                continue;
        //            }

        //            if (string.Compare(
        //                    IntegrationKitUtilities.GetROStringProperty(step, "Name"),
        //                    currentName,
        //                    StringComparison.OrdinalIgnoreCase) == 0)
        //            {
        //                step["Name"].StringValue = newName;
        //                return true;
        //            }
        //        }
        //        return false;
        //    }
        //    catch (Exception e)
        //    {
        //        Console.WriteLine("Failed To enumerate task sequence items: " + e.Message);
        //        throw;
        //    }
        //}


        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="taskSequence" type="Microsoft.ConfigurationManagement.ManagementProvider.IResultObject">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="packageId" type="string">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        ///// </returns>
        //public IResultObject AddCustomRebootSteps(ConnectionManagerBase conn, IResultObject taskSequence, string packageId)
        //{
        //    try
        //    {

        //        if (GroupWithConditionExists(taskSequence, "RebootStep") == true)
        //        {
        //            //we already have a group inserted for the reboot to PXE task.
        //            DialogHelper.ShowMessageBox(Properties.Resources.CRA_Error_CustomRebootTemplateAlreadyApplied);
        //            return null;
        //        }
        //        //

        //        IResultObject group1 = IntegrationKitUtilities.CreateTaskSequenceGroup(
        //            (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn,
        //            Properties.Resources.CRA_Group_HardwareConfig,
        //            Properties.Resources.TaskSequenceGroup_HardwareConfig_Desc, true, true);
        //        if (group1 != null)
        //        {
        //            group1 = AddVariableCondition(conn, group1, Properties.Resources.RebootStepVariable, "1", operatorLessThan);
        //            group1 = AddVariableCondition(conn, group1, Properties.Resources.RebootStepVariable, "", operatorNotExists);
        //            group1 = IntegrationKitUtilities.JoinTaskSequenceConditionExpressions(
        //                (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn, group1, "or", 0, 1);

        //            if (group1 != null)
        //            {
        //                IResultObject group2 = IntegrationKitUtilities.CreateTaskSequenceGroup(
        //                    (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn,
        //                    Properties.Resources.CRA_Group_PostHardwareConfig,
        //                    Properties.Resources.TaskSequenceGroup_PostHardwareConfig_Desc, true, true);
        //                if (group2 != null)
        //                {
        //                    group2 = AddVariableCondition(conn, group2, Properties.Resources.RebootStepVariable, "2", operatorGreaterEqual);
        //                    if (group2 != null)
        //                    {

        //                        List<IResultObject> steps = taskSequence.GetArrayItems("Steps");
        //                        List<IResultObject> group1Steps = group1.GetArrayItems("Steps");
        //                        List<IResultObject> group2Steps = group2.GetArrayItems("Steps");

        //                        StepNumber = 0;
        //                        group1Steps.AddRange(MoveNodes(conn, steps, 0, RebootStepId));
        //                        StepNumber = 0;
        //                        group2Steps.AddRange(MoveNodes(conn, steps, RebootStepId + 1, TotalSteps));

        //                        if (IntegrationKitUtilities.IsTaskSequenceActionTypeInStepList(group2Steps, Properties.Resources.CRA_StepTypeReset) == false)
        //                        {
        //                            IResultObject newAction = CreateResetVarAction(conn, packageId);
        //                            group2Steps.Add(newAction);
        //                        }

        //                        // Add the groups to the beginning of the task sequence.
        //                        group1.SetArrayItems("Steps", group1Steps);
        //                        group2.SetArrayItems("Steps", group2Steps);

        //                        int j = steps.Count;
        //                        for (int i = 0; i < j; i++)
        //                        {
        //                            steps.Remove(steps[0]);
        //                        }

        //                        steps.Add(group1);
        //                        steps.Add(group2);

        //                        if (IntegrationKitUtilities.IsTaskSequenceActionTypeInStepList(steps, Properties.Resources.CRA_StepTypeSet) == false)
        //                        {
        //                            IResultObject newAction = CreateSetVarAction(conn, packageId);
        //                            steps.Add(newAction);
        //                        }


        //                        //save the steps
        //                        taskSequence.SetArrayItems("Steps", steps);

        //                    }
        //                    else
        //                    {
        //                        DialogHelper.ShowMessageBox("Error adding the variable condition to the \"Post Hardware Config\" group!");
        //                    }
        //                }
        //                else
        //                {
        //                    DialogHelper.ShowMessageBox("Error creating the \"Post Hardware Config\" group!");
        //                }
        //            }
        //            else
        //            {
        //                DialogHelper.ShowMessageBox("Error adding the variable condition to the \"Hardware Config\" group!");
        //            }
        //        }
        //        else
        //        {
        //            DialogHelper.ShowMessageBox("Error creating the \"Hardware Config\" group!");
        //        }

        //        return taskSequence;
        //    }
        //    catch (Exception e)
        //    {
        //        DialogHelper.ShowMessageBox("Exception encountered during AddCustomRebootSteps().\n\n" + e.Message);
        //        return null;
        //    }
        //}

        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="taskSequence" type="Microsoft.ConfigurationManagement.ManagementProvider.IResultObject">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        ///// </returns>
        //public IResultObject InsertRebootStepsIntoExistingTaskSequence(IResultObject taskSequence)
        //{
        //    //start by adding the "Set Step Variable" action (after 
        //    return null;
        //}

        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="editor" type="Microsoft.ConfigurationManagement.AdminConsole.TaskSequenceEditor.TaskSequenceEditorDialog">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="parentNode" type="Microsoft.ConfigurationManagement.AdminConsole.OsdCommon.SmsTreeNode">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A bool value...
        ///// </returns>
        //public bool ReformatTaskSequence(ConnectionManagerBase conn, TaskSequenceEditorDialog editor, SmsTreeNode parentNode)
        //{
        //    try
        //    {
        //        IResultObject taskSequencePackage = null;
        //        IResultObject taskSequence =
        //            IntegrationKitUtilities.GetTaskSequenceOpenInEditor(
        //            (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn,
        //            editor,
        //            parentNode,
        //            out taskSequencePackage);


        //        if ((taskSequence != null) & (taskSequencePackage != null))
        //        {
        //            taskSequence = InsertRebootStepsIntoExistingTaskSequence(taskSequence);

        //            if (taskSequence != null)
        //            {
        //                IResultObject newPackage = IntegrationKitUtilities.SaveTaskSequenceToPackage(
        //                    (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn,
        //                    taskSequence,
        //                    taskSequencePackage);

        //                if (newPackage != null)
        //                {
        //                    return true;
        //                }
        //            }
        //        }
        //        else
        //        {
        //            DialogHelper.ShowMessageBox(Properties.Resources.Error_TaskSequenceNameNotFound);
        //        }
        //        return false;
        //    }
        //    catch (Exception e)
        //    {
        //        DialogHelper.ShowMessageBox(e.Message);
        //        return false;
        //    }

        //}

        ////private bool IsSelectedTaskSequence(IResultObject taskSequence)
        //{
        //    try
        //    {
        //        SmsTreeNode node = this.ParentNode;
        //        SmsTreeNode topNode = null;
        //        List<SmsTreeNode> nodeList = new List<SmsTreeNode>();
        //        List<SmsTreeNode> topNodes = new List<SmsTreeNode>();

        //        string prevNode = null;
        //        string nextNode = null;
        //        string currentNode = null;
        //        if (node != null)
        //        {
        //            currentNode = node.Text;
        //            topNode = IntegrationKitUtilities.GetSmsTreeNodeTop(node);
        //            while (topNode != null)
        //            {
        //                topNodes.Add(topNode);
        //                topNode = topNode.NextNode;
        //            }
        //            nodeList = IntegrationKitUtilities.GetFlatSmsTreeNodeList(topNodes);
        //        }

        //        int nodeIndex = nodeList.IndexOf(node);
        //        if (nodeIndex != 0)
        //        {
        //            if (nodeList[nodeIndex - 1] != null)
        //            {
        //                prevNode = nodeList[nodeIndex - 1].Text;
        //            }
        //        }
        //        else
        //        {
        //            DialogHelper.ShowMessageBox("The 'Reboot To PXE' step is the first step in the task sequence.\n\nThis action serves no purpose as the first action in a task sequence. Either move or delete this action.");
        //            return false;
        //        }
        //        if (nodeIndex != nodeList.Count - 1)
        //        {
        //            if (nodeList[nodeIndex + 1] != null)
        //            {
        //                nextNode = nodeList[nodeIndex + 1].Text;
        //            }
        //        }
        //        else
        //        {
        //            DialogHelper.ShowMessageBox("The 'Reboot To PXE' step is the last step in the task sequence.\n\nThis action serves no purpose as the last action in a task sequence. Either move or delete this action.");
        //            return false;
        //        }


        //        int stepId = FindStepId(taskSequence, prevNode, currentNode, nextNode);
        //        if (stepId > -1)
        //        {
        //            RebootStepId = stepId;
        //            return true;
        //        }
        //        else
        //        {
        //            return false;
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        DialogHelper.ShowMessageBox("Exception occurred during IsSelectedTaskSequence.\n" + e.Message);
        //        return false;
        //    }

        //}

        //private int FindStepId(IResultObject taskSequence, string prevStep, string currentStep, string nextStep)
        //{
        //    try
        //    {
        //        bool prevMatch = false;
        //        bool currentMatch = false;
        //        bool nextMatch = false;

        //        List<IResultObject> flatStepList = IntegrationKitUtilities.GetFlatTaskSequenceStepList(taskSequence);

        //        IResultObject stepObj = null;
        //        IResultObject prevStepObj = null;
        //        IResultObject nextStepObj = null;

        //        TotalSteps = flatStepList.Count;

        //        for (int i = 0; i < flatStepList.Count; i++)
        //        {
        //            stepObj = flatStepList[i];
        //            if (string.Compare(currentStep, stepObj["Name"].StringValue) == 0)
        //            {
        //                if (i == 0)
        //                {
        //                    DialogHelper.ShowMessageBox("The 'Reboot To PXE' step is the first step in the task sequence.\n\nThis action serves no purpose as the first action in a task sequence. Either move or delete this action.");
        //                    return -1;
        //                }
        //                else if ((i > 0) && (i == (flatStepList.Count - 1)))
        //                {
        //                    DialogHelper.ShowMessageBox("The 'Reboot To PXE' step is the last step in the task sequence.\n\nThis action serves no purpose as the last action in a task sequence. Either move or delete this action.");
        //                    return -1;
        //                }
        //                else
        //                {
        //                    currentMatch = true;

        //                    if (i > 0)
        //                    {
        //                        prevStepObj = flatStepList[i - 1];
        //                        if (prevStep == null)
        //                        {
        //                            if (string.Compare("SMS_TaskSequence_Group", prevStepObj["__CLASS"].StringValue) == 0)
        //                            {
        //                                prevMatch = true;
        //                            }
        //                            else
        //                            {
        //                                prevMatch = false;
        //                            }
        //                        }
        //                        else if (string.Compare(prevStep, prevStepObj["Name"].StringValue) == 0)
        //                        {
        //                            prevMatch = true;
        //                        }
        //                        else
        //                        {
        //                            prevMatch = false;
        //                        }
        //                    }

        //                    if (i < flatStepList.Count - 1)
        //                    {
        //                        nextStepObj = flatStepList[i + 1];
        //                        if (nextStep == null)
        //                        {
        //                            if (string.Compare("SMS_TaskSequence_Group", nextStepObj["__CLASS"].StringValue) == 0)
        //                            {
        //                                nextMatch = true;
        //                            }
        //                            else
        //                            {
        //                                nextMatch = false;
        //                            }
        //                        }
        //                        else if (string.Compare(nextStep, nextStepObj["Name"].StringValue) == 0)
        //                        {
        //                            nextMatch = true;
        //                        }
        //                        else
        //                        {
        //                            nextMatch = false;
        //                        }
        //                    }
        //                }
        //                if ((currentMatch == true) && (prevMatch == true) && (nextMatch == true))
        //                {
        //                    RebootNodeObj = stepObj;
        //                    return i;
        //                }
        //            }
        //        }

        //        DialogHelper.ShowMessageBox("Could not verify the task sequence being edited.\n\nPlease save the task sequence first, close and re-open the editor and select \"Reboot to PXE\" again.");
        //        return -1;

        //    }
        //    catch (SmsException e)
        //    {
        //        Console.WriteLine("Exception occurred while enumerating the task sequence: " + e.Message);
        //        return -1;
        //    }
        //}

        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="packageId" type="string">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        ///// </returns>
        //public IResultObject CreateSetVarAction(ConnectionManagerBase conn, string packageId)
        //{
        //    try
        //    {
        //        IResultObject newAction = conn.CreateEmbeddedObjectInstance("IDK_RebootToPxe");

        //        //newAction["CommandLine"].StringValue = "\"cmd /c echo.%RebootToPxeScript%> RebootToPxe.vbs\" && \"cscript RebootToPxe.vbs %1 %2\"";
        //        newAction["PackageID"].StringValue = packageId;
        //        newAction["Name"].StringValue = Properties.Resources.CRA_SetRebootStepVariableHeader;
        //        newAction["Description"].StringValue = Properties.Resources.CRA_SetRebootStepVariableText;
        //        newAction["Enabled"].BooleanValue = true;
        //        newAction["ContinueOnError"].BooleanValue = false;
        //        newAction["SupportedEnvironment"].StringValue = "WinPEandFullOs";
        //        newAction["Timeout"].IntegerValue = 300;

        //        newAction["AlreadyApplied"].BooleanValue = true;
        //        newAction["AlreadySetGroups"].BooleanValue = true;
        //        newAction["ChkMessage"].BooleanValue = false;
        //        newAction["Message"].StringValue = "";
        //        newAction["MessageTimeout"].StringValue = "0";
        //        newAction["StepType"].StringValue = Properties.Resources.CRA_StepTypeSet;

        //        newAction["WillRunFromPxe"].BooleanValue = true;
        //        newAction["WillReboot"].BooleanValue = false;
        //        newAction["StepNumber"].IntegerValue = 0;

        //        newAction = AddVariableCondition(conn, newAction, "PxeRebootStep", "0", operatorGreaterThan);
        //        newAction = AddVariableCondition(conn, newAction, "PxeRebootStep", "2", operatorLessThan);
        //        newAction = IntegrationKitUtilities.JoinTaskSequenceConditionExpressions(
        //            (ManagementProvider.WqlQueryEngine.WqlConnectionManager)conn, newAction, "and", 0, 1);

        //        return newAction;
        //    }
        //    catch (SmsException e)
        //    {
        //        DialogHelper.ShowMessageBox("Failed to create 'Set PxeRebootStep' Task Sequence\n" + e.Message);
        //        return null;
        //    }
        //}

        ///// <summary>
        /////     
        ///// </summary>
        ///// <param name="conn" type="Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <param name="packageId" type="string">
        /////     <para>
        /////         
        /////     </para>
        ///// </param>
        ///// <returns>
        /////     A Microsoft.ConfigurationManagement.ManagementProvider.IResultObject value...
        ///// </returns>
        //public IResultObject CreateResetVarAction(ConnectionManagerBase conn, string packageId)
        //{
        //    try
        //    {
        //        IResultObject ro = conn.CreateEmbeddedObjectInstance("IDK_RebootToPxe");

        //        //newAction["CommandLine"].StringValue = "\"cmd /c echo.%RebootToPxeScript%> RebootToPxe.vbs\" && \"cscript RebootToPxe.vbs %1 %2\"";
        //        ro["PackageID"].StringValue = packageId;
        //        ro["Name"].StringValue = Properties.Resources.CRA_ResetRebootVariableHeader;
        //        ro["Description"].StringValue = Properties.Resources.CRA_ResetRebootVariableText;
        //        ro["Enabled"].BooleanValue = true;
        //        ro["ContinueOnError"].BooleanValue = false;
        //        ro["SupportedEnvironment"].StringValue = "WinPE";
        //        ro["Timeout"].IntegerValue = 300;

        //        ro["AlreadyApplied"].BooleanValue = true;
        //        ro["AlreadySetGroups"].BooleanValue = true;
        //        ro["ChkMessage"].BooleanValue = false;
        //        ro["Message"].StringValue = "";
        //        ro["MessageTimeout"].StringValue = "0";
        //        ro["StepType"].StringValue = Properties.Resources.CRA_StepTypeReset;
        //        ro["WillRunFromPxe"].BooleanValue = true;
        //        ro["WillReboot"].BooleanValue = false;
        //        ro["StepNumber"].IntegerValue = 0;

        //        return ro;
        //    }
        //    catch (SmsException e)
        //    {
        //        DialogHelper.ShowMessageBox("Failed to create 'Reset PxeRebootStep' Task Sequence\n" + e.Message);
        //        return null;
        //    }
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="conn"></param>
        ///// <param name="stepList"></param>
        ///// <param name="firstNodeId"></param>
        ///// <param name="lastNodeId"></param>
        ///// <returns></returns>
        //public List<IResultObject> MoveNodes(ConnectionManagerBase conn, List<IResultObject> stepList, int firstNodeId, int lastNodeId)
        //{
        //    try
        //    {
        //        List<IResultObject> newStepList = new List<IResultObject>();
        //        IResultObject step = null;

        //        int count = stepList.Count;
        //        int j = 0;
        //        for (int i = 0; i < count; i++)
        //        {
        //            if (StepNumber <= lastNodeId)
        //            {
        //                step = stepList[j];
        //                if (step["__CLASS"].StringValue == "SMS_TaskSequence_Group")
        //                {
        //                    IResultObject newGroup = IntegrationKitUtilities.CopyTaskSequenceGroup(conn, step);
        //                    List<IResultObject> array = step.GetArrayItems("Steps");
        //                    StepNumber++;
        //                    newGroup.SetArrayItems("Steps", MoveNodes(conn, array, firstNodeId, lastNodeId));

        //                    //array = step.GetArrayItems("Steps");
        //                    if (array.Count == 0)
        //                    {
        //                        //stepList.Remove(step);
        //                        j++;
        //                    }
        //                    else
        //                    {
        //                        j++;
        //                    }

        //                    //check to see if group was empty. If so, don't add it.
        //                    List<IResultObject> array2 = newGroup.GetArrayItems("Steps");
        //                    if (array2.Count > 0)
        //                    {
        //                        newStepList.Add(newGroup);
        //                    }

        //                }
        //                else
        //                {
        //                    if (StepNumber >= firstNodeId)
        //                    {
        //                        if (StepNumber == RebootStepId)
        //                        {
        //                            step["AlreadySetGroups"].BooleanValue = true;
        //                        }
        //                        newStepList.Add(step);
        //                        //stepList.Remove(step);
        //                        j++;
        //                    }
        //                    else
        //                    {
        //                        //don't do anything until we get to the starting point - just loop.
        //                        j++;
        //                    }
        //                    StepNumber++;
        //                }


        //            }
        //            else
        //            {
        //                break;
        //            }
        //        }
        //        return newStepList;
        //    }
        //    catch (Exception e)
        //    {
        //        DialogHelper.ShowMessageBox("Exception encountered during MoveNodes().\n\n" + e.Message);
        //        return null;
        //    }
        //}

    }
}